package models

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"strconv"
)

type ResourceElb struct {
	Model // 不用每次写ID 和 createAt了
	ResourceCommon

	// 重点字段
	LoadBalancerType   string       `json:"LoadBalancerType" gorm:"comment:类型有 nlb alb clb"`
	BandwidthCapacity  int          `json:"BandwidthCapacity" gorm:"comment:带宽包上限 50Mb 100Mb"`
	AddressType        string       `json:"AddressType" gorm:"comment:公网类型还是内网类型"`
	DNSName            string       `json:"DNSName" gorm:"comment: dns解析地址"`
	BandwidthPackageId string       `json:"BandwidthPackageId" gorm:"comment:绑定的带宽包"`
	CrossZoneEnabled   bool         `json:"CrossZoneEnabled" `
	BindNodes          []*StreeNode `json:"bind_nodes" gorm:"many2many:bind_elbs;"` // 多对多
}

// 生成hash值
func (rh *ResourceElb) GenHash() string {
	h := md5.New()
	h.Write([]byte(rh.InstanceId))
	h.Write([]byte(rh.LoadBalancerType))
	h.Write([]byte(rh.DNSName))
	h.Write([]byte(strconv.Itoa(rh.BandwidthCapacity)))
	return hex.EncodeToString(h.Sum(nil))
}

// 添加elb资源
func (obj *ResourceElb) Create() error {
	return DB.Create(obj).Error
}

// 级联删除elb资源
func (obj *ResourceElb) DeleteOne() error {
	return DB.Select(clause.Associations).Unscoped().Delete(obj).Error

}

// 根据ID级联去删除elb资源
func DeleteResourceElbOneByInstanceId(iid string) error {
	return DB.Select(clause.Associations).Unscoped().Where("instance_id = ?", iid).Delete(&ResourceElb{}).Error
}

// 添加elb资源
func (obj *ResourceElb) CreateOne() error {
	return DB.Create(obj).Error

}

// 更新elb资源
func (obj *ResourceElb) UpdateOne() error {
	return DB.Where("id = ?", obj.ID).Updates(obj).Error
}

// 更新绑定树节点和对应的elb资源
func (obj *ResourceElb) UpdateBindNodes(nodes []*StreeNode) error {
	return DB.Model(obj).Association("BindNodes").Replace(nodes)
}

// 获取elb所有资源
func GetResourceElbAll() (objs []*ResourceElb, err error) {
	err = DB.Preload("BindNodes").Find(&objs).Error
	return
}

// 根据elb资源层级做预加载
func GetResourceElbByLevel(level int) (objs []*ResourceElb, err error) {
	err = DB.Where("level = ?", level).Preload("OpsAdmins").Find(&objs).Error
	return
}

// ELB翻页展示分页限制处理
func GetResourceElbByIdsWithLimitOffset(ids []int, limit, offset int) (objs []*ResourceElb, err error) {
	err = DB.Limit(limit).Offset(offset).Find(&objs, ids).Error
	return
}

// 根据instanceId 去数据库中查找elb资源
func GetResourceElbByInstanceId(instanceId string) (*ResourceElb, error) {
	var dbObjs ResourceElb
	err := DB.Where("instance_id = ?", instanceId).Preload("BindNodes").First(&dbObjs).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("ResourceElb not found")
		}
		return nil, fmt.Errorf("ResourceElb query failed: %s", err)
	}
	return &dbObjs, nil
}

func GetResourceElbById(id int) (*ResourceElb, error) {
	var dbObj ResourceElb
	err := DB.Where("id = ?", id).Preload("BindNodes").First(&dbObj).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("ResourceElb not found")
		}
		return nil, fmt.Errorf("ResourceElb query failed: %s", err)
	}
	return &dbObj, nil
}

func GetResourceElbUidAndHash() (map[string]string, error) {
	var objs []*ResourceElb
	err := DB.Find(&objs).Error
	if err != nil {
		return nil, err
	}
	m := make(map[string]string)
	for _, h := range objs {
		m[h.InstanceId] = h.GenHash()
	}
	return m, nil
}

// 获取特定服务树节点绑定的资源列表， 给删除叶子节点时做校验如果绑定了资源，则不允许删除
func GetResourceElbBoundToNode(nodeID uint) ([]*ResourceElb, error) {
	allElb, err := GetResourceElbAll()
	if err != nil {
		return nil, err
	}

	var boundResources []*ResourceElb
	for _, elb := range allElb {
		elb := elb
		for _, bindNode := range elb.BindNodes {
			if bindNode.ID == nodeID {
				boundResources = append(boundResources, elb)
				break
			}
		}
	}
	return boundResources, nil
}
